Fix: Infinite recursion crash in wikitext parser#308
Conversation
There was a problem hiding this comment.
Pull request overview
This PR fixes a critical infinite recursion bug in the wikitext parser that was causing StackOverflowError crashes when parsing certain Wikipedia templates. The solution implements a two-pronged approach: a recursion depth guard and hardening of template parameter extraction.
Key changes:
- Added a ThreadLocal recursion depth counter with a maximum depth of 64 to gracefully handle deeply nested or malformed wikitext
- Fixed 18+ template handlers to use
substringAfter('|', "")with an empty string default, preventing self-recursion when templates lack parameters
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Looks good to me. Can you please fix the changes Copilot has suggested? Otherwise it's good. |
…tedString.kt Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…tedString.kt Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot suggestions accepted. |
|
Hey, I'm really sorry for not merging this PR for so long, I've been having a lack of time recently and I was working on another app, and i couldn't work on this at all. I'll merge this tomorrow. Thanks for your patience! |
|
Thanks for contributing! |
|
Pleasure! I’ll try to contribute more going forward 🙂 |
Problem
The app kept crashing with a StackOverflowError on some Wikipedia pages because the
toWikitextAnnotatedStringfunction was getting stuck in an endless loop. Certain templates like{{small}}were sending the same wikitext back into the parser again and again, which caused the function to call itself repeatedly until the app crashed.Stack Trace Sample
Solution
Implemented a two-part fix:
1. Recursion Depth Guard
AnnotatedString(this)) instead of crashingtry/finallyblock to ensure proper cleanup of the recursion counter2. Template Branch Hardening
substringAfter('|')tosubstringAfter('|', "")for templates like:{{abbr}},{{efn}},{{val}},{{var}},{{small}}family,{{dfn}},{{US$}},{{hatnote}},{{rp}},{{isbn}},{{sfrac}},{{unichar}},{{char}},{{noflag}},{{nowrap}}family,{{url}},{{format price}},{{transliteration}}|parameter, the parser receives an empty string instead of the full template text, preventing self-recursionChanges
app/src/main/java/org/nsh07/wikireader/parser/wikitextToAnnotatedString.ktMAX_WIKITEXT_RECURSION_DEPTHconstant (64)WikitextParserStateobject with thread-local recursion countertoWikitextAnnotatedStringfunctionTesting
StackOverflowErrorNotes